#include"demuxthread.h"

DemuxThread::DemuxThread(AVPacketQueue* audio_packet_q, AVPacketQueue* video_packet_q) {
	this->audio_packet_q = audio_packet_q;
	this->video_packet_q = video_packet_q;
}
DemuxThread::~DemuxThread() {
	if (mythread) {
		Stop();
	}
}
int DemuxThread::Init(const string& url) {
	int ret = 0;
	this->url = url;

	ifmt_ctx = avformat_alloc_context();

	ret = avformat_open_input(&ifmt_ctx, url.c_str(), NULL, NULL);
	if (ret < 0) {
		perror("demuxthread: avformat_open_input failed");
		return -1;
	}

	ret = avformat_find_stream_info(ifmt_ctx, NULL);
	if (ret < 0) {
		perror("demuxthread: avformat_find_stream_info failed");
			return -1;
	}

	for (unsigned int i = 0; i < ifmt_ctx->nb_streams; i++) {
		if (ifmt_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
			video_index = i;
			break;
		}
	}
	if (video_index < 0 ) {
		perror("demuxthread: avformat video stream index failed");
		return -1;
	}
	for (unsigned int i = 0; i < ifmt_ctx->nb_streams; i++) {
		if (ifmt_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
			audio_index = i;
			break;
		}
	}
	if (audio_index < 0) {
		perror("demuxthread: avformat audio stream index failed");
		return -1;
	}
	return 0;
}
int DemuxThread::Start() {
	mythread = new thread(&Run, this);
	if (!mythread) {
		perror("demuxthread: new a thread failed");
		return -1;
	}
	return 0;
}
int DemuxThread::Stop() {
	Thread::Stop();
	avformat_close_input(&ifmt_ctx);
	return 0;
}

void DemuxThread::Run() {
	int ret = 0;
	AVPacket pack;
	while (abort != 1){
		ret = av_read_frame(ifmt_ctx, &pack);
		if (ret < 0) {
			perror("demuxthread: av_read_frame failed");
			break;
		}
		if (pack.stream_index == audio_index) {
			audio_packet_q->Push(&pack);
		}else if (pack.stream_index == video_index) {
			video_packet_q->Push(&pack);
		}else{
			av_packet_unref(&pack);
		}
	}
}

AVCodecParameters* DemuxThread::AudioCodecParameters(){
	if(audio_index != -1){
		return ifmt_ctx->streams[audio_index]->codec.codecpar;
	}else{
		return nullptr;
	}
}

AVCodecParameters* DemuxThread::VideoCodecParameters(){
	if(video_index != -1){
		return ifmt_ctx->streams[video_index]->codec.codecpar;
	}else{
		return nullptr;
	}
}

AVRational DemuxThread::AudioStreamTimebase(){
	if(audio_index != -1){
		return ifmt_ctx->streams[audio_index]->time_base;
	}else{
		return AVRational{0, 0};
	}
}

AVRational DemuxThread::VideoStreamTimebase(){
	if(video_index != -1){
		return ifmt_ctx->streams[video_index]->time_base;
	}else{
		return AVRational{0, 0};
	}
}